package com.amos.muexamclient.security.service.impl;

import com.amos.constant.Constants;
import com.amos.exception.BizExceptionEnum;
import com.amos.muexamclient.framework.service.RedisService;
import com.amos.muexamclient.framework.service.TokenService;
import com.amos.muexamclient.security.service.PermissionService;
import com.amos.muexamclient.security.service.SysLoginService;
import com.amos.muexamclient.sys.service.SysMenuService;
import com.amos.muexamclient.sys.service.dto.LoginUser;
import com.amos.muexamclient.sys.service.dto.SysMenuDTO;
import com.amos.muexamclient.sys.service.dto.SysUserDTO;
import com.amos.muexamclient.util.MessageUtils;
import com.amos.muexamcore.util.ServletUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Copyright © 2018 嘉源锐信. All rights reserved.
 *
 * @Project: mu-exam
 * @ClassName: SysLoginServiceImpl
 * @Package: com.amos.muexamclient.sys.service.impl
 * @author: zhuqb
 * @Description: 登录
 * @date: 2020/3/24 0024 下午 16:27
 * @Version: V1.0
 */
@Service
public class SysLoginServiceImpl implements SysLoginService {
    @Autowired
    RedisService redisService;

    @Autowired
    TokenService tokenService;
    @Resource
    private AuthenticationManager authenticationManager;

    @Autowired
    private PermissionService permissionService;

    @Autowired
    private SysMenuService menuService;

    @Override
    public String login(String username, String password, String code, String uuid) {

        String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid;
        String verifyCode = redisService.getKey(verifyKey) + "";
        BizExceptionEnum.NOT_NULL.definedMsg(MessageUtils.message("user.jcaptcha.expire")).notNullAssert(verifyCode);
        if (!code.equalsIgnoreCase(verifyCode)) {
            BizExceptionEnum.DEFINED_EXCEPTION.definedMsg(MessageUtils.message("user.jcaptcha.error")).throwException();
        }
        // 用户验证
        Authentication authentication = null;
        try {
            // 该方法会去调用 UserDetailsServiceImpl.loadUserByUsername
            authentication = authenticationManager
                    .authenticate(new UsernamePasswordAuthenticationToken(username, password));
        } catch (Exception e) {
            String message = "";
            if (e instanceof BadCredentialsException) {
                message = MessageUtils.message("user.password.not.match");
            } else {
                message = e.getMessage();
            }
            BizExceptionEnum.DEFINED_EXCEPTION.definedMsg(message).throwException();
        }
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        loginUser.setId(loginUser.getUser().getId());
        return tokenService.createToken(loginUser);
    }

    @Override
    public Map<String, Object> getInfo() {
        HttpServletRequest request = ServletUtils.getRequest();
        LoginUser loginUser = tokenService.getLoginUser(request);
        return this.getInfo(loginUser);
    }

    public Map<String, Object> getInfo(LoginUser loginUser) {
        Map<String, Object> map = new HashMap<>();
        SysUserDTO user = loginUser.getUser();
        user.setId(loginUser.getId());
        map.put("user", user);
        map.put("roles", permissionService.getRolePermission(user));
        map.put("permissions", permissionService.getMenuPermission(user));
        return map;
    }

    @Override
    public List<SysMenuDTO> getRouters() {
        HttpServletRequest request = ServletUtils.getRequest();
        LoginUser loginUser = tokenService.getLoginUser(request);
        SysUserDTO userDTO = loginUser.getUser();
        userDTO.setId(loginUser.getId());
        return menuService.selectMenuTreeByUserId(userDTO);
    }
}
